package com.fh.utils.socket;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fh.dto.MessageDto;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.List;

/**
 * @author sungp
 * @description: WebSocket
 * @date 2023年01月17日 11:03
 */
@Data
@Slf4j
@Component
@ServerEndpoint(value = "/websocket/{userId}")
public class WebSocket {

    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;

    /**
     * 用户ID
     */
    private String userId;

    /**
     * @author sungp
     * @description: 创建WebSocket连接成功时调用此方法
     * @date 2023年01月17日 11:22
     * @param session session
     * @param userId 用户标识
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "userId") String userId){
        this.session = session;
        this.userId = userId;
        if(WsSessionManager.get(userId) == null) {
            WsSessionManager.add(userId , this);
            log.info("[onOpen] 用户{}加入WebSocket连接" , userId);
            return;
        }
        StringBuffer use = new StringBuffer("userId");
        use.append(": ").append(userId).append(" 已经存在，不可以重复连接");
        session.getAsyncRemote().sendText(String.valueOf(use));
    }

    /**
     * @author sungp
     * @description: 收到客户端消息后调用的方法
     * @date 2023年01月17日 11:23
     * @param message json格式参数
     * {
     *     "userId": "发送方id",
     *     "targetIds": [
     *         "接收方id"
     *     ],
     *     "data": "消息"
     * }
     */
    @OnMessage
    public void onMessage(String message){
        log.info("[onMessage] 收到用户{}发来的消息：{}" , userId , message);
        MessageDto messageDto = JSON.parseObject(message, MessageDto.class);
        JSONObject jsonObject = JSON.parseObject(message);
        jsonObject.remove("targetIds");
        sendMessage(jsonObject.toString() , messageDto.getTargetIds());
    }

    /**
     * @author sungp
     * @description: 发送消息
     * @date 2023年01月17日 13:44
     * @param messageData 消息数据
     * @param userIds 目标用户id
     */
    public void sendMessage(String messageData , List<String> userIds){
        for (String userId : userIds) {
            //获取对应目标用户的MyWebSocket对象
            WebSocket webSocket = WsSessionManager.get(userId);
            if (!ObjectUtils.isEmpty(webSocket) && webSocket.getSession().isOpen()){
                //向目标发送消息
                webSocket.getSession().getAsyncRemote().sendText(messageData);
                log.info("[sendMessage] 用户{}为在线状态，消息发送成功！" , userId);
            }else {
                log.info("[sendMessage] 用户{}为离线状态，消息未发送成功！" , userId);
            }
        }
    }

    /**
     * @author sungp
     * @description: 关闭连接
     * @date 2023年01月17日 13:59 参数
     */
    @OnClose
    public void onClose(){
        WsSessionManager.removeAndClose(userId);
    }


    /**
     * @author sungp
     * @description: 发生错误
     * @date 2023年01月17日 14:04
     * @param session session
     * @param error 参数
     */
    @OnError
    public void onError(Session session, Throwable error){
        String errMsg = "正确消息格式：{\n" +
                "    \"userId\": \"发送方id\",\n" +
                "    \"targetIds\": [\n" +
                "        \"接收方id\"\n" +
                "    ],\n" +
                "    \"data\": \"消息\"\n" +
                "}";
        session.getAsyncRemote().sendText(errMsg);
        System.out.println("发生错误，请注意");
        error.printStackTrace();
    }


}
